package com.secsys.dao.impl;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.sql.SQLException;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.transform.Transformers;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.secsys.dao.HibernateBaseDAO;

/**
 * @className HibernateBaseDAOImpl
 * @Description HibernateBaseDAO接口实现类
 * @author LiuQ
 * @date 2011-3-28 2:27
 * @param <T>
 *            领域都像
 * @param <PK>
 *            主键类型
 */
public class HibernateBaseDAOImpl<T, PK extends Serializable> extends
		HibernateDaoSupport implements HibernateBaseDAO<T, PK> {

	// 实体类类型（由构造方法自动赋值）
	private Class<T> entityObject;

	/**
	 * 根据构造方法自动获取实体类类型
	 */
	@SuppressWarnings("unchecked")
	public HibernateBaseDAOImpl() {
		this.entityObject = null;
		Class<?> clazz = getClass();
		Type type = clazz.getGenericSuperclass();
		if (type instanceof ParameterizedType) {
			Type[] param = ((ParameterizedType) type).getActualTypeArguments();
			this.entityObject = (Class<T>) param[0];
		}

	}

	/**
	 * 构造方法，根据实例类自动获取SessionFactory和实体类类型
	 * 
	 * @param sessionFactory
	 * @param entityObject
	 */
	public HibernateBaseDAOImpl(SessionFactory sessionFactory,
			Class<T> entityObject) {
		super.setSessionFactory(sessionFactory);
		this.entityObject = entityObject;
	}

	/**
	 * 根据主键获取实体，如果没有则返回null值
	 */
	public T get(PK id) {
		return (T) getHibernateTemplate().get(entityObject, id);
	}

	/**
	 * 根据主键获取实体，如果没有则抛出异常
	 */
	public T load(PK id) {
		return (T) getHibernateTemplate().load(entityObject, id);
	}

	/**
	 * 获取所有实体
	 */
	public List<T> loadAll() {
		return getHibernateTemplate().loadAll(entityObject);
	}

	/**
	 * 更新实体
	 */
	public void update(T entity) {
		getHibernateTemplate().update(entity);
	}

	/**
	 * 存储实体到数据库
	 */
	public void save(T entity) {
		getHibernateTemplate().save(entity);
	}

	/**
	 * 增加或更新实体
	 */
	public void saveOrUpdate(T entity) {
		getHibernateTemplate().saveOrUpdate(entity);
	}

	/**
	 * 增加或更新对象
	 */
	public void saveObjectReturn(Object obj) {
		getHibernateTemplate().saveOrUpdate(obj);
	}

	/**
	 * 增加或更新集合中的全部实体
	 */
	public void saveOrUpdateAll(Collection<T> entities) {
		getHibernateTemplate().saveOrUpdateAll(entities);
	}

	/**
	 * 删除实体
	 */
	public void delete(T entity) {
		getHibernateTemplate().delete(entity);

	}

	/**
	 * 根据主键删除实体
	 */
	public void deleteByKey(PK id) {
		getHibernateTemplate().delete(load(id));
	}

	/**
	 * 删除集合中的所有实体
	 */
	public void deleteAll(Collection<T> entities) {
		getHibernateTemplate().deleteAll(entities);
	}
	
	/**
	 * 根据id获取所在对象的实体类对象
	 */
	@SuppressWarnings("unchecked")
	public Object getObject(Class clazz, Serializable id) {
		return getHibernateTemplate().get(clazz, id);
	}
	/**
	 * 根据id删除对象，id用于获取所在对象的实体类对象
	 */
	@SuppressWarnings("unchecked")
	public void removeObject(Class clazz, Serializable id) {
		Object obj = getObject(clazz, id);
		getHibernateTemplate().delete(obj);
	}

	// -------------HQL----------------------//

	/**
	 * 使用HSQL语句直接增加、更新、删除实体
	 */
	public int bulkUpdate(String queryString) {
		return getHibernateTemplate().bulkUpdate(queryString);
	}

	/**
	 * 使用带参数的HSQL语句增加、更新、删除实体(不支持级联)
	 */
	public int bulkUpdate(String queryString, Object[] values) {
		return getHibernateTemplate().bulkUpdate(queryString, values);
	}

	/**
	 * 使用HSQL语句检索数据
	 */
	@SuppressWarnings("unchecked")
	public List<T> find(String queryString) {
		return getHibernateTemplate().find(queryString);
	}
	
	@SuppressWarnings("unchecked")
	public List<Object> findObject(String queryString) {
		return getHibernateTemplate().find(queryString);
	}

	/**
	 * 返回分页多表查询的Object类型的List数据
	 * @param 	queryString
	 * 				不带参数的多表查询的HSQL语句
	 * @param offset 
	 * 			-分页的起始索引
	 * @param size
	 * 			-显示条数
	 * 				
	 * @return 	List<Object[]>
	 * 				返回多表查询结果的“多个对象数组”的List，也就是List<Object[]>
	 */
	@SuppressWarnings("unchecked")
	public List<Object> findObject(final String queryString,final int offset,final int count){
		List<Object> list = getHibernateTemplate().executeFind(new HibernateCallback() {
			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				Query query = session.createQuery(queryString);
				List result = query.setFirstResult(offset).setMaxResults(count).list();
				return result; 
			}
		});
		return list;
	}
	
	/**
	 * 使用带参数的HSQL语句检索数据
	 */
	@SuppressWarnings("unchecked")
	public List<T> find(String queryString, Object[] values) {
		return getHibernateTemplate().find(queryString, values);
	}
	
	@SuppressWarnings("unchecked")
	public List<Object> findObject(String queryString, Object[] values) {
		return getHibernateTemplate().find(queryString, values);
	}

	/**
	 * 返回多表查询的Object类型的List数据
	 * @author 	tiger.hu
	 * @param 	queryString
	 * 				带参数的多表查询的HSQL语句
	 * @param 	values
	 * 				参数值数组
	 * @param 	offset 
	 * 			-分页的起始索引
	 * @param	size
	 * 			-显示条数
	 * 				
	 * @return 	List<Object[]>
	 * 				返回多表查询结果的“多个对象数组”的List，也就是List<Object[]>
	 */
	@SuppressWarnings("unchecked")
	public List<Object> findObject(final String queryString, final Object[] objects,final int offset,final int count){
		if (objects ==null || objects.length < 1){
			return findObject(queryString, offset, count);
		}
		List<Object> list = getHibernateTemplate().executeFind(new HibernateCallback() {
			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				Query query = session.createQuery(queryString);
				for (int i = 0; i < objects.length; i++) {
					query.setParameter(i, objects[i]); 
				}
				List result = query.setFirstResult(offset).setMaxResults(count).list();
				return result;
			}
		}); 
		return list;
	}
	
	/**
	 * 使用带参数的HQL语句检索数据
	 */
	@SuppressWarnings("unchecked")
	public List<T> findByProperty(String queryString, Object value) {
		return getHibernateTemplate().find(queryString, value);
	}

	/**
	 * 使用带命名的参数的HSQL语句检索数据
	 */
	@SuppressWarnings("unchecked")
	public List<T> findByNamedParam(String queryString, String[] paramNames,
			Object[] values) {
		return getHibernateTemplate().findByNamedParam(queryString, paramNames,
				values);
	}

	/**
	 * 使用命名的HSQL语句检索数据
	 */
	@SuppressWarnings("unchecked")
	public List<T> findByNamedQuery(String queryName) {
		return getHibernateTemplate().findByNamedQuery(queryName);
	}

	/**
	 * 使用带参数的命名HSQL语句检索数据
	 */
	@SuppressWarnings("unchecked")
	public List<T> findByNamedQuery(String queryName, Object[] values) {
		return getHibernateTemplate().findByNamedQuery(queryName, values);
	}

	/**
	 * 使用带命名参数的命名HSQL语句检索数据
	 */
	@SuppressWarnings("unchecked")
	public List<T> findByNamedQueryAndNamedParam(String queryName,String[] paramNames, Object[] values) {
		return getHibernateTemplate().findByNamedQueryAndNamedParam(queryName,
				paramNames, values);
	}

	/**
	 * 使用HSQL语句检索数据，返回 Iterator
	 */
	@SuppressWarnings("unchecked")
	public Iterator<T> iterate(String queryString) {
		return getHibernateTemplate().iterate(queryString);
	}

	/**
	 * 使用带参数HSQL语句检索数据，返回 Iterator
	 */
	@SuppressWarnings("unchecked")
	public Iterator<T> iterate(String queryString, Object[] values) {
		return getHibernateTemplate().iterate(queryString, values);
	}

	/**
	 * 关闭检索返回的 Iterator
	 */
	public void closeIterator(Iterator<T> it) {
		getHibernateTemplate().closeIterator(it);
	}

	/**
	 * 使用HQL语句检索满足标准的记录数
	 */
	public Integer findCount(String hql) {
		Integer count = ((Long) getHibernateTemplate().iterate(hql).next())
				.intValue();
		return count;
	}

	// --------------------其他----------------//
	/**
	 * 强制初始化指定的实体
	 */
	public void initialize(Object proxy) {
		getHibernateTemplate().initialize(proxy);
	}

	/**
	 * 强制立即更新缓冲数据到数据库（否则仅在事务提交时才更新）
	 */
	public void flush() {
		getHibernateTemplate().flush();
	}

	public void clear() {
		getHibernateTemplate().clear();
	}

	@SuppressWarnings("unchecked")
	public Integer count() {
		String sql = "SELECT COUNT(*) FROM " + entityObject.getSimpleName();
		List<T> list = getHibernateTemplate().find(sql);
		return list != null && list.size() > 0 ? ((Long) list.get(0))
				.intValue() : 0;
	}

	@SuppressWarnings("unchecked")
	public Integer count(String hql) {
		List<T> list = getHibernateTemplate().find(hql);
		return list != null && list.size() > 0 ? ((Long) list.get(0))
				.intValue() : 0;
	}

	@SuppressWarnings("unchecked")
	public Integer count(final String hql, final Map<String, Date> map) {
		if (map.size() < 1)
			return count(hql);
		List<T> list = getHibernateTemplate().executeFind(
				new HibernateCallback() {
					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						Query query = session.createQuery(hql);
						Set<String> set = map.keySet();
						for (String key : set) {
							query.setDate(key, map.get(key));
						}
						return query.list();
					}
				});
		return list != null && list.size() > 0 ? ((Long) list.get(0))
				.intValue() : 0;
	}

	
	/**
	 * 根据对象获取所有实体
	 */
	@SuppressWarnings("unchecked")
	@Override
	public List<?> loadAll(Class cass) {
		return getHibernateTemplate().loadAll(cass);
	}

	/**
	 * 使用带参数的SQL语句检索数据
	 */
	@SuppressWarnings("unchecked")
	@Override
	public List<T> findBySql(String sql, Class<?> clazz, Object[] values,Object[][] obj) {
		SQLQuery sqlQuery = this.getSession().createSQLQuery(sql);
		if (obj != null) {
			for (Object[] element : obj) {
				sqlQuery.addScalar((String) element[0],
						(org.hibernate.type.Type) element[1]);
			}
		}
		if (clazz != null) {
			sqlQuery.setResultTransformer(Transformers.aliasToBean(clazz));
		}
		if (values != null) {
			for (int i = 0; i < values.length; i++) {
				sqlQuery.setParameter(i, values[i]);
			}
		}
		List<T> list = sqlQuery.list();
		return list;
	}

	/**
	 * 分页查询
	 * 
	 * @param queryString
	 *            -hql语句
	 * @param offset
	 *            -起始索引
	 * @param size
	 *            -显示条数
	 * @return
	 */
	@SuppressWarnings("unchecked")
	@Override
	public List<T> findBySql(final String queryString, final int offset,final int size) {
		List<T> list = getHibernateTemplate().executeFind(new HibernateCallback() {
			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				Query query = session.createQuery(queryString);
				List result = query.setFirstResult(offset).setMaxResults(size)
						.list();
				return result;
			}
		});
		return list;
	}

	/**
	 * 分页查询
	 * 
	 * @param queryString
	 *            -hql语句
	 * @param offset
	 *            -起始索引
	 * @param size
	 *            -显示条数
	 * @param map
	 *            -日期参数键值对
	 * @return
	 */
	@SuppressWarnings("unchecked")
	@Override
	public List<T> findBySql(final String queryString, final int offset,final int size, final Map<String, Date> map) {
		if (map.size() < 1)
			return findBySql(queryString, offset, size);
		List list = getHibernateTemplate().executeFind(new HibernateCallback() {
			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {

				Query query = session.createQuery(queryString);
				Set<String> set = map.keySet();
				logger.info("set size is :" + set.size());
				for (String key : set) {
					logger.info(key + ":" + set.size());
					query.setDate(key, map.get(key));
				}
				List result = query.setFirstResult(offset).setMaxResults(size)
						.list();
				return result;
			}
		});
		return list;
	}

	/**
	 * 利用带参数的hql语句分页查询
	 * @author tiger.hu
	 * @param queryString
	 * @param objects
	 * 			-参数值数组
	 * @param offset 
	 * 			-分页的起始索引
	 * @param size
	 * 			-显示条数
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<T> findBySql(final String queryString,final Object[] objects,final int offset,final int size) {
		if (objects ==null || objects.length < 1){
			return findBySql(queryString, offset, size);
		}
		List<T> list = getHibernateTemplate().executeFind(new HibernateCallback() {
			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {

				Query query = session.createQuery(queryString);
				for (int i = 0; i < objects.length; i++) {
					query.setParameter(i, objects[i]);
				}
				List result = query.setFirstResult(offset).setMaxResults(size)
						.list();
				return result;
			}
		});
		return list;
	}
	
	/**
	 * 使用带参数的SQL语句检索数据(指定记录数)
	 */
	@SuppressWarnings("unchecked")
	@Override
	public List<T> findBySql(String sql, Class<?> clazz, Object[] values,
			Object[][] obj, int offset, int size) {
		SQLQuery sqlQuery = this.getSession().createSQLQuery(sql);
		if (obj != null) {
			for (Object[] element : obj) {
				sqlQuery.addScalar((String) element[0],
						(org.hibernate.type.Type) element[1]);
			}
		}
		if (clazz != null) {
			sqlQuery.setResultTransformer(Transformers.aliasToBean(clazz));
		}
		if (values != null) {
			for (int i = 0; i < values.length; i++) {
				sqlQuery.setParameter(i, values[i]);
			}
		}
		Query query = sqlQuery;
		query.setFirstResult(offset).setMaxResults(size);
		List<T> list = query.list();
		return list;
	}
  public void merge(T entity){
	  getSession().merge(entity);
  }
  /**
   * 
   * @Description sql语句方式统计对象 
   * @param sql
   * @return
   */
  public List getCount(String sql){
	 Session session= getHibernateTemplate().getSessionFactory().openSession();  //取得session对象
	  SQLQuery query=session.createSQLQuery(sql);
	  List list= query.list();
	  return list;
  }
  
  
}
